import { injectable } from "inversify";
import { BaseCustomFunctionService } from "../base_class/BaseCustomFunctionService";
import {
  FunctionPlugin,
  FunctionArgumentType,
  HyperFormula,
  CellError,
  ErrorType,
} from "hyperformula";
import { ErrorMessage } from "../data/ErrorMessage";
import { SimpleDateTime } from "hyperformula/typings/DateTimeHelper";
import { FormulaService } from "./FormulaService";
import { myContainer } from "../inversify/inversify.config";
import { InterpreterState } from "hyperformula/typings/interpreter/InterpreterState";

/**
 * 暂时没内容，仅用于让下面的注册自定义的函数生效
 */
@injectable()
export class CustomFunctionService extends BaseCustomFunctionService {
  constructor() {
    super();
  }
}

type timediftype = {
  h: number;
  m: number;
  s: number;
};

/**
 * 不知道应该遵循inversify的什么原则，放在哪里
 */
export class DateCustomedPlugin extends FunctionPlugin {
  dateString(ast: any, state: any) {
    return this.runFunction(
      ast.args,
      state,
      this.metadata("DATESTRING"),
      (dateNumber: number) => {
        const formulaService = myContainer.get(
          FormulaService
        ) as FormulaService;
        const hf = formulaService.hf;
        const datetime: SimpleDateTime = hf.numberToDateTime(
          dateNumber
        ) as SimpleDateTime;

        return `${datetime.year}-${datetime.month}-${datetime.day} ${datetime.hours}:${datetime.minutes}:${datetime.seconds}`;
        // return ``;
      }
    );
  }
  private timeNumber2timedif(timeNumber: number): timediftype {
    const 小数部分 = timeNumber - Math.trunc(timeNumber);
    const totalSeconds = Math.trunc(小数部分 * 86400);
    const h = Math.trunc(totalSeconds / 3600);
    const m = Math.trunc((totalSeconds % 3600) / 60);
    const s = totalSeconds % 60;
    return { h, m, s };
  }
  timeDif(ast: any, state: any) {
    return this.runFunction(
      ast.args,
      state,
      this.metadata("TIMEDIF"),
      (startTime: number, endTime: number, unit: string = "S") => {
        if (startTime > endTime) {
          return new CellError(ErrorType.NUM, ErrorMessage.StartEndDate);
        }
        const start = this.timeNumber2timedif(startTime);
        const end = this.timeNumber2timedif(endTime);
        switch (unit) {
          case "H":
            if (end.m > start.m || (end.m === start.m && end.s >= start.s)) {
              return end.h - start.h;
            } else {
              return end.h - start.h - 1;
            }
            break;
          case "M":
            return (
              (end.h - start.h) * 60 +
              (end.m - start.m) -
              (end.s < start.s ? 1 : 0)
            );
            break;
          case "S":
            const end_type = this.timeNumber2timedif(endTime);
            const start_type = this.timeNumber2timedif(startTime);
            const endTimeTotalSeconds =
              end_type.h * 3600 + end_type.m * 60 + end_type.s;
            const startTimeTotalSeconds =
              start_type.h * 3600 + start_type.m * 60 + start_type.s;
            return endTimeTotalSeconds - startTimeTotalSeconds;
            break;

          default:
            return new CellError(ErrorType.NUM, ErrorMessage.BadMode);
            break;
        }
      }
    );
  }
  fixed(ast: any, state: InterpreterState) {
    return this.runFunction(
      ast.args,
      state,
      this.metadata("FIXED"), // 关键
      (number: number, decimal_places: number = 0): string => {
        return number.toFixed(decimal_places);
      }
    );
  }
}

DateCustomedPlugin.implementedFunctions = {
  DATESTRING: {
    method: "dateString",
    parameters: [{ argumentType: FunctionArgumentType.NUMBER }],
  },
  TIMEDIF: {
    method: "timeDif",
    parameters: [
      { argumentType: FunctionArgumentType.NUMBER, minValue: 0 },
      { argumentType: FunctionArgumentType.NUMBER, minValue: 0 },
      {
        argumentType: FunctionArgumentType.STRING,
        optionalArg: true,
        defaultValue: "S",
      },
    ],
  },
  FIXED: {
    method: "fixed",
    parameters: [
      { argumentType: FunctionArgumentType.NUMBER },
      {
        argumentType: FunctionArgumentType.NUMBER,
        optionalArg: true,
        defaultValue: 0,
        minValue: 0,
      },
    ],
  },
};

HyperFormula.registerFunctionPlugin(DateCustomedPlugin, {
  enGB: {
    DATESTRING: "DATESTRING",
    TIMEDIF: "TIMEDIF",
    FIXED: "FIXED",
  },
  //   enUS: {
  //     GREET: "GREET",
  //   },
});
